package com.two.screen.water.balance.serial.battery

import com.cyItem.sesrialPort.SerialPort
import com.cyItem.sesrialPort.SerialPortFinder
import com.two.screen.water.balance.bean.WeightBean
import com.two.screen.water.balance.utils.*
import com.two.screen.water.balance.utils.UtilsBigDecimal.toDoubleWithTwoDecimalPlaces
import com.two.screen.water.balance.utils.eventbus.Event
import com.two.screen.water.balance.utils.eventbus.EventBusUtil
import com.two.screen.water.balance.utils.eventbus.EventCode
import java.io.File
import java.io.InputStream

object SerialPortBatteryZzUtils {
    private var mSerialPort: SerialPort? = null
    private var mInputStream: InputStream? = null
    private var mReadThread: Thread? = null
    private var mDevicePathArray: Array<String>? = null
    private var mDevicePath: String? = null
    private var mSerialPortPath = "/dev/ttyS7"
    private var mSerialPortPort = 115200

    fun initSerialPortBattery() {
        close()
        mSerialPortPath = "/dev/ttyS7"
        mDevicePathArray = SerialPortFinder().allDevicesPath

        if (mDevicePathArray == null || mDevicePathArray!!.isEmpty()) {
            return
        }
        mDevicePathArray?.forEach {
            if (mSerialPortPath == it) {
                mDevicePath = it
            }
            d("串口：$it")
        }
        d("串口：确认：$mDevicePath")
        if (mDevicePath.isNullOrBlank()) {
            return
        }

        mSerialPort = try {
            SerialPort(File(mSerialPortPath), mSerialPortPort, 0)
        } catch (e: Exception) {
            d("串口通信失败，请重试！")
            closeSerialPort()
            return
        }

        mInputStream = mSerialPort?.inputStream
        if (mInputStream == null) {
            d("电子秤端口或者波特率未正确配置！")
            closeSerialPort()
            return
        }
        mReadThread = ReadThread()
        mReadThread!!.start()
    }

    fun close() {
        closeThreadQuiet()
        closeSerialPort()
    }

    //关闭线程
    private fun closeThreadQuiet() {
        if (mReadThread != null) {
            try {
                mReadThread?.interrupt()
            } catch (e: java.lang.Exception) {
                // just ignore
            } finally {
                mReadThread = null
            }
        }
    }

    //关闭串口
    private fun closeSerialPort() {
        if (mSerialPort != null) {
            try {
                if (mInputStream != null) {
                    mInputStream!!.close()
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
            if (mSerialPort!!.isOpen) {
                mSerialPort!!.closePort()
            }
            mSerialPort = null
        }
    }


    //每一包数据最大长度
    private val mZzDataMaxSize = 24

    //缓存区长度
    private val mZzBuffSize = mZzDataMaxSize * 2

    //缓存区
    private val mZzBuff = ByteArray(mZzBuffSize)

    //缓存区可存入的下一个数据下标（即已存入的数据长度）
    private var mZzBuffIndex = 0

    //头
    private val mZzHead = byteArrayOf(0XAA.toByte(), 0XBB.toByte())

    //输出
    private var mZzOutBuff: ByteArray? = null

    //每条数据长度
    private var mZzDataLength = 24

    internal class ReadThread : Thread() {
        override fun run() {
            // 读取数组
            val bytes = ByteArray(24)
            while (true) {
                try {
                    if (isInterrupted) break
                    val len = mInputStream!!.read(bytes)
                    if (len < 20) continue
                    d("处理前：${ByteUtils.toHexString(bytes)}")
                    bytes.forEach { oneByte ->
                        if (mZzBuffIndex >= mZzBuff.size) {
                            //缓存区已满，删除第一个
                            if (mZzBuff.size - 1 >= 0) {
                                System.arraycopy(mZzBuff, 1, mZzBuff, 0, mZzBuff.size - 1)
                                mZzBuff[mZzBuff.size - 1] = 0X00
                                mZzBuffIndex = mZzBuff.size - 1
                            }
                        }
                        mZzBuff[mZzBuffIndex] = oneByte
                        mZzBuffIndex++
                        //新数据已加入缓存，从缓存中检验是否有完整数据
                        xsVerificationData()
                    }

                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                }
            }
        }
    }

    //新数据已加入缓存，从缓存中检验是否有完整数据
    private fun xsVerificationData() {
        //System.out.println("BUFF：" +Arrays.toString(buff));
        if (mZzBuffIndex < 7) {
            //头+长度+data +校验+尾 就算数据为空也至少要4位
        } else {
            //帧头 第一个 0xAA
            if (mZzBuff[0] == mZzHead[0]) {
                //帧头 第二个 0xBB
                if (mZzBuff[1] == mZzHead[1]) {
                    //数据长度
                    val dataLengthByteArray = byteArrayOf(mZzBuff[2], mZzBuff[3])
                    val bytes2HexStr = ByteUtils.bytes2HexStr(dataLengthByteArray)
                    val dataLength = Integer.parseInt(bytes2HexStr, 16)
                    //d("xsVerificationData::dataLength:$dataLength")

                    if (dataLength in 1..mZzDataMaxSize) {
                        if (mZzBuffIndex >= dataLength) {
                            var tmp = mutableListOf<Byte>()
                            for (i in 0..dataLength - 3) {
                                tmp.add(mZzBuff[i])
                            }
                            val str = ByteUtils.bytes2HexStr(tmp.toByteArray())
                            val crc = ByteUtils.bytes2HexStr(byteArrayOf(mZzBuff[dataLength - 1], mZzBuff[dataLength - 2]))
                            //d("校验CRC=>crc(str)：${CRC16Utils.getCRC16_Modbus_Str(str)}")
                            var isCrc = CRC16Utils.CheckCrc16Modbus(str, crc)

                            //校验CRC 这里有问题，crc不对
                            //d("校验CRC=>isCrc：${isCrc},str：${str},crc:$crc")
                            if (isCrc) {
                                //打印 CRC
                                //d("xsVerificationData::crc:$crc,mXSBuff[mZzDataLength-1]:${mZzBuff[mZzDataLength - 1]}")
                                mZzOutBuff = ByteArray(dataLength)
                                System.arraycopy(mZzBuff, 0, mZzOutBuff, 0, mZzDataLength)
                                //use outBuff
                                mZzOutBuff?.let { handRealDataXS(it) }

                                //清除已使用数据
                                System.arraycopy(mZzBuff, mZzDataLength, mZzBuff, 0, mZzDataLength)
                                for (i in 0 until mZzDataLength) {
                                    mZzBuff[mZzBuffIndex - mZzDataLength + i] = 0X00
                                }
                                mZzBuffIndex -= mZzDataLength
                                //再次检验
                                xsVerificationData()
                            } else {
                                System.arraycopy(mZzBuff, 1, mZzBuff, 0, mZzBuffIndex - 1)
                                mZzBuff[mZzBuffIndex - 1] = 0X00
                                mZzBuffIndex -= 1
                                //再次检验
                                xsVerificationData()
                            }

                        } else {
                            //已缓存的数据还没有这没多，继续等待缓存
                            //本方法可能存在干扰数据正好与hed相等，然后第二位是干扰数据或者是真的数据hed,此时把第二位当数据长度会出现问题
                            //比如缓存中有数据3B 28 3B 09 ..... 0A，其中3B 28为干扰数据，后面还有个完整的数据包，
                            //那么此方法会等到再有数据进来，缓存中有0X28个数据时才会判断出3B 28为无效数据，就造成了延时问题，
                            //或者后面不会再有数据进来，那么后面那个真的完整数据就会存在缓存中而没有拿出来使用。
                            //解决办法：
                            //一、增加hed头为多个字节，减少干扰和hed的相等的几率。
                            //二、在此继续向后面检查是否有完整数据，但是检测前不清除前面的buff,如果有的话再清空buff中的使用数据和前面的无效数据
                        }
                    } else {
                        //数据长度超过规定长度，肯定是错误数据，舍弃1位
                        System.arraycopy(mZzBuff, 1, mZzBuff, 0, mZzBuffIndex - 1)
                        mZzBuff[mZzBuffIndex - 1] = 0X00
                        mZzBuffIndex -= 1
                        //再次检验
                        xsVerificationData()
                    }
                } else {
                    //第二个数据不是hed,舍弃
                    System.arraycopy(mZzBuff, 2, mZzBuff, 0, mZzBuffIndex - 2)
                    mZzBuff[mZzBuffIndex - 1] = 0X00
                    mZzBuff[mZzBuffIndex - 2] = 0X00
                    mZzBuffIndex -= 2
                    //再次检验
                    xsVerificationData()
                }

            } else {
                //第一个数据不是hed,舍弃
                System.arraycopy(mZzBuff, 1, mZzBuff, 0, mZzBuffIndex - 1)
                mZzBuff[mZzBuffIndex - 1] = 0X00
                mZzBuffIndex -= 1
                //再次检验
                xsVerificationData()
            }
        }
    }

    /*处理分析zz数据*/
    fun handRealDataXS(data: ByteArray) {
        //共24字节
        var d1 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[5], data[6])), 16)
        var d2 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[7])), 16)
        var d3 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[8], data[9])), 16)
        var d4 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[10])), 16)
        var d5 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[11])), 16)
        var d6 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[19])), 16)
        var d7 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[20])), 16)
        var d8 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[21])), 16)

        var d9 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[12], data[13])), 16)
        var d10 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[14])), 16)
        var d11 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[15], data[16])), 16)
        var d12 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[17])), 16)
        var d13 = Integer.parseInt(ByteUtils.bytes2HexStr(byteArrayOf(data[18])), 16)


        var str1 = "电池电压（单位mV）：${d1}mV"
        var str2 = "电池温度（单位℃）：${d2}℃"
        var str3 = "电池电流（单位mA）：${d3}mA"
        var str4 = "电池电量百分比（单位％）：${d4}％"
        var str5 = "电池健康指数（单位％）：${d5}％"
        var str6 = "主电源固件版本：${d6}"
        var str7 = "内电池充电或者放电：${if (d7 == 0) "放电" else if (d7 == 1) "充电" else "未知"}"//0放电，1充电
        var str8 = "外电流充或者放电：${if (d8 == 0) "放电" else if (d8 == 1) "充电" else "未知"}"//0放电，1充电


        var str9 = "外电池电压：${d9}mV"
        var str10 = "外电池温度：${d10}℃"
        var str11 = "外电池电流：${d11}mA"
        var str12 = "外电池电量百分比：${d12}％"
        var str13 = "外电池健康指数：${d13}％"



        //d("处理后：${ByteUtils.bytes2HexStr(data)}")
        d(str1)
        d(str2)
        d(str3)
        d(str4)
        d(str5)
        d(str6)
        d(str7)
        d(str8)
        d(str9)
        d(str10)
        d(str11)
        d(str12)
        d(str13)
        d("------------------------------------------------")
        d("")
        d("")
        d("")


    }

    fun d(msg: String) {
        CommUtils.println("SerialPortBatteryZzUtils->", msg)
    }
}